#include "MWindow.h"
#include <X11/Xlib.h>
#include <X11/keysym.h>

namespace RayTracer
{
    static Window w;
    static GC gc;
    static Display *dpy;
    static int black;
    static unsigned int color = 0;

    static bool running = true;
    
    void MWindow::InitNativeWindowSystem()
    {
	dpy = XOpenDisplay(0);
	black = BlackPixel(dpy, DefaultScreen(dpy));
	w = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), 0, 0, width, height, 0, black, black);
	XSelectInput(dpy, w, StructureNotifyMask | ExposureMask | KeyPressMask);
    }
        
    void MWindow::Show()
    {
	XMapWindow(dpy, w);
	gc = XCreateGC(dpy, w, 0, 0);

	while(running)
	{
	    XEvent e;
	    XNextEvent(dpy, &e);
	    switch(e.type)
	    {
	    case MapNotify:
	    case Expose:
		this->IterateScreen();
		break;
	    case DestroyNotify:
		running = false;
		break;
	    case KeyPress:
		this->HandleKeyPressed(&e);
		break;
	    }
	}
    }

    static KeySym GetKeySym(KeyCode code)
    {
	int keySymCount = 0;
	KeySym *syms = XGetKeyboardMapping(dpy, code, 1, &keySymCount);
	
	return keySymCount > 0 ? syms[0] : 0;
    }

    void MWindow::HandleKeyPressed(void *keyData)
    {
	XKeyPressedEvent *e = (XKeyPressedEvent*)keyData;
		
	switch(GetKeySym(e->keycode))
	{
	case XK_Escape:
	    running = false;
	    XFreeGC(dpy, gc);
	    XDestroyWindow(dpy, w);
	    XCloseDisplay(dpy);
	    return;
	};
    }

    void MWindow::DrawPixel(int x, int y, const Color *c)
    {
	MWindow::ConvertToNativeColor(c);
	XSetForeground(dpy, gc, color);
	XDrawPoint(dpy, w, gc, x, y);
    }

    void MWindow::ConvertToNativeColor(const Color *c)
    {
	int r = c->GetR() * 255.0f;
	int g = c->GetG() * 255.0f;
	int b = c->GetB() * 255.0f;

	color = 0;
	
	color |= r << 16;
	color |= g << 8;
	color |= b;
    }
};
